package com.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class JT808 {
    public static final int IMAGE_PACKAGESIZE = 960;
    private byte[] databuff = new byte[1024*200];
    private int datapos = 0;

    public static void PutShort(byte[] data, int istart ,int value ){
        data[istart] = (byte)(value & 0xFF);
        data[istart + 1]  = (byte)((value >> 8) & 0xFF);
    }

    public static void PutInt(byte[] data, int istart ,int value ){
        data[istart] = (byte)(value & 0xFF);
        data[istart + 1]  = (byte)((value >> 8) & 0xFF);
        data[istart + 2] = (byte)((value >> 16) & 0xFF);
        data[istart + 3]  = (byte)((value >> 24) & 0xFF);
    }

    public static byte[] ToBcd(String src,int ilen) {
        byte[] dest = new byte[ilen/2];
        int index = 0;
        for(int i=0;i<src.length();i+=2){
            int v1 =  Integer.parseInt(src.substring(i,i+1));
            int v2 =  Integer.parseInt(src.substring(i+1,i+2));
            dest[index] = (byte)((v1 << 4 ) + v2);
            index++;
        }
        return dest;
    }

    public byte[] TransData(){
        ByteBuffer buff = ByteBuffer.allocate(1024);
        buff.put(databuff[0]);
        for(int i=1;i<datapos-1;i++){
            if (databuff[i]==0x7e){
                buff.put((byte)0x7d);
                buff.put((byte)0x2);
            }else if (databuff[i]==0x7d) {
                buff.put((byte)0x7d);
                buff.put((byte)0x1);
            }else{
                buff.put(databuff[i]);
            }
        }
        buff.put(databuff[datapos-1]);
        buff.flip();
        byte[] result = new byte[buff.remaining()];
        buff.get(result);
        return result;
    }

    public static byte[] ResumeTransData(byte[] data){
        ByteBuffer buff = ByteBuffer.wrap(data);
        ByteBuffer newbuff = ByteBuffer.allocate(1024);
        while (buff.hasRemaining()){
            if(buff.remaining()>1){
                int value = buff.getShort() & 0xffff;
                if (value==0x17d)
                    newbuff.put((byte)0x7d);
                else if(value==0x27d)
                    newbuff.put((byte)0x7e);
                else
                    newbuff.putShort((short) value);
            }else {
                newbuff.put(buff.get());
            }
        }
        newbuff.flip();
        byte[] result = new byte[newbuff.remaining()];
        newbuff.get(result);
        return result;
    }

    public interface JTData {
        public JTData pushSubAddone(int id, int ilen, byte[] data);
        public byte[]  getSubAddone();
    }
    public class JT808_Head{
        private short id;
        private short prop;
        private byte[] phone = new byte[6];
        private short seq;
        private short packageCount;
        private short packageIndex;

        public JT808_Head(int id, int prop, String phone, int seq, int pkCount,int pkIndex) {
            this.id = (short) id;
            this.prop =(short) prop;
            byte[] bcdphone = ToBcd(phone,12);
            System.arraycopy(bcdphone,0,this.phone,0,Math.min(this.phone.length,bcdphone.length));
            this.seq = (short)seq;
            packageCount = (short) pkCount;
            packageIndex = (short) pkIndex;
            if(packageCount>0)
                this.prop |= (1<<13);
        }

        public JT808_Head(byte[] data){
            ByteBuffer buff =  ByteBuffer.wrap(data);
            buff.get();
            id = buff.getShort();
            prop = buff.getShort();
            buff.get(phone,0,6);
            seq = buff.getShort();
        }

        public byte[] Encode(){
            ByteBuffer buff = ByteBuffer.allocate(1024);
            buff.putShort(id);
            buff.putShort(prop);
            buff.put(phone);
            buff.putShort(seq);
            if(packageCount>0) {
                buff.putShort(packageCount);
                buff.putShort(packageIndex);
            }
            buff.flip();
            byte[] result = new byte[buff.remaining()];
            buff.get(result);
            return result;
        }
    }

    public class JT808_Reg{
        private short  provinceID;
        private short cityID;
        private byte[] manufacturer= new byte[5];
        private byte[] mode = new byte[20];
        private byte[] pid= new byte[7];
        private byte color;
        private String platenumber;

        public JT808_Reg( int provinceID, int cityID, String manufacturer, String mode, String pid, int color, String platenumber) {
            this.provinceID = (short) provinceID;
            this.cityID =  (short) cityID;
            System.arraycopy(manufacturer.getBytes(),0,this.manufacturer,0,Math.min(this.manufacturer.length,manufacturer.getBytes().length));
            System.arraycopy(mode.getBytes(),0,this.mode,0,Math.min(this.mode.length,mode.getBytes().length));
            //System.arraycopy(pid.getBytes(),0,this.pid,0,Math.min(this.pid.length,pid.getBytes().length));
            this.pid = ToBcd(pid,14);
            this.color = (byte)color;
            //System.arraycopy(platenumber.getBytes(),0,this.platenumber,0,Math.min(this.platenumber.length,platenumber.getBytes().length));
            this.platenumber = platenumber;
        }

        public byte[] Encode(){
            ByteBuffer buff = ByteBuffer.allocate(1024);
            buff.putShort(provinceID);
            buff.putShort(cityID);
            buff.put(manufacturer);
            buff.put(mode);
            buff.put(pid);
            buff.put(color);
            buff.put(platenumber.getBytes());
            buff.flip();
            byte[] result = new byte[buff.remaining()];
            buff.get(result);
            return result;
        }
    }

    public class JT808_Loc implements JTData{
        private int warning;
        private int status;
        private int lng;
        private int lat;
        private short high;
        private short speed;
        private short direct;
        private byte[] time = new byte[6];

        ByteBuffer Addone = ByteBuffer.allocate(1024);
        ByteBuffer SubAddone = ByteBuffer.allocate(1024);


        public void pushAddone(int id,int ilen,byte[] data){
            Addone.put((byte)id);
            Addone.put((byte)ilen);
            Addone.put(data,0,ilen);
        }

        public void pushAddone(int id,byte data){
            Addone.put((byte)id);
            Addone.put((byte)1);
            Addone.put(data);
        }

        public void pushAddone(int id,short data){
            Addone.put((byte)id);
            Addone.put((byte)2);
            Addone.putShort(data);
        }

        @Override
        public JTData pushSubAddone(int id,int ilen,byte[] data){
            SubAddone.put((byte)id);
            SubAddone.put((byte)ilen);
            SubAddone.put(data,0,ilen);
            return this;
        }

        @Override
        public byte[]  getSubAddone(){
            SubAddone.flip();
            byte[] result = new byte[SubAddone.remaining()];
            SubAddone.get(result);
            return result;
        }

        public JT808_Loc(int warning, int status, int lng, int lat, int high, int speed, int direct, String time) {
            this.warning = warning;
            this.status = status;
            this.lng = lng;
            this.lat = lat;
            this.high =(short) high;
            this.speed = (short) speed;
            this.direct = (short) direct;

            byte[] bcdtime = ToBcd(time,12);
            System.arraycopy(bcdtime,0,this.time,0,Math.min(this.time.length,bcdtime.length));
        }

        //获取定位的实体数据
        public byte[] getBytes(){
            ByteBuffer buff = ByteBuffer.allocate(1024);
            buff.putInt(warning);
            buff.putInt(status);
            buff.putInt(lng);
            buff.putInt(lat);
            buff.putShort(high);
            buff.putShort(speed);
            buff.putShort(direct);
            buff.put(time);
            buff.flip();
            byte[] result = new byte[buff.remaining()];
            buff.get(result);
            return result;
        }
        public byte[] Encode(){
            ByteBuffer buff = ByteBuffer.allocate(1024);
            buff.putInt(warning);
            buff.putInt(status);
            buff.putInt(lng);
            buff.putInt(lat);
            buff.putShort(high);
            buff.putShort(speed);
            buff.putShort(direct);
            buff.put(time);

            Addone.flip();
            if(Addone.remaining()>0) {
                buff.put(Addone);
            }

            buff.flip();
            byte[] result = new byte[buff.remaining()];
            buff.get(result);
            return result;
        }
    }

    public class JT808_Media{
        private int mediaId;//不确定是否为分包序号
        private byte mediaType;
        private byte mediaFormat;
        private byte eventId;
        private byte chnId;
        private String mediaName;
        public long mediasize;

        public JT808_Media(int mediaId, byte mediaType, byte mediaFormat, byte eventId, byte chnId,String mediaFilename) {
            this.mediaId = mediaId;
            this.mediaType = mediaType;
            this.mediaFormat = mediaFormat;
            this.eventId = eventId;
            this.chnId = chnId;
            mediaName = mediaFilename;

            try {
                File srcFile = new File(mediaName);
                if (srcFile.exists()) {
                    mediasize = srcFile.length();
                } else
                    mediasize = 0;
            }catch (Exception e){
                mediasize = 0;
            }
        }

        ByteBuffer Addone = ByteBuffer.allocate(1024);

        //先加添加位置信息,在添加图片内容,
        public void pushAddone(byte[] data){
            Addone.put(data,0,data.length);
        }
        public int packageImage(int iseq){
            try {
                FileInputStream inputStream = new FileInputStream(mediaName);
                inputStream.skip(iseq*IMAGE_PACKAGESIZE);
                byte[] buf = new byte[IMAGE_PACKAGESIZE];
                int count = inputStream.read(buf,0,IMAGE_PACKAGESIZE);
                if (count>0){
                    Addone.put(buf,0,count);
                }else
                    return 0;
                inputStream.close();
                return count;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 0;
        }

        public void reset(){
            Addone.clear();
            //Addone = ByteBuffer.allocate(1024);
        }

        public byte[] Encode(int iSeq){
            ByteBuffer buff = ByteBuffer.allocate(1024);
            packageImage(iSeq);
            if(iSeq==0) {
                buff.putInt(mediaId);
                buff.put(mediaType);
                buff.put(mediaFormat);
                buff.put(eventId);
                buff.put(chnId);
            }
            Addone.flip();
            if(Addone.remaining()>0) {
                buff.put(Addone);
            }

            buff.flip();
            byte[] result = new byte[buff.remaining()];
            buff.get(result);
            return result;
        }
    }

    public static byte[] getMacInfo(float angle1,float angle2,float depth){
        ByteBuffer data = ByteBuffer.allocate(12);
        data.put((byte)(angle1>0?1:0));
        data.putInt((int)(angle1));
        data.put((byte)(angle2>0?1:0));
        data.putInt((int)(angle2));
        data.putShort((short) (depth));
        return data.array();
    }

    public static int getAntStatus(boolean isAntOpen,boolean isAntShort){
        int v = 0;
        v+=  (isAntOpen?1:0)<<4;
        v+=  (isAntShort?1:0)<<5;
        return v;
    }

    public static int getGpsStatus(int gpsStatus,boolean ismakeup){
        int v = gpsStatus>0?1:0;
        v +=  1<<17;   //0： 未使用GPS 卫星进行定位； 1： 使用GPS 卫星进行定位
        v +=  1<<18;   // 0： 未使用北斗卫星进行定位； 1： 使用北斗卫星进行定位
        v +=  2<<28;  //0x01 有效定位     0x11 高精度定位
        v +=  (ismakeup?1:0)<<30;
        return v;
    }

    public int checkXor(int ilen,boolean isCheck){
        byte v = 0;
        for(int i=1;i<ilen;i++)
        {
            v ^= databuff[i];
        }

        if(isCheck){
            return databuff[ilen]==v?1:0;
        }
        return v;
    }

    public void PoackageData(JT808_Head head,byte[] data){
        databuff[0]= 0x7e;
        datapos++;
        byte[] _head = head.Encode();
        System.arraycopy(_head,0,databuff,datapos,_head.length);
        datapos += _head.length;
        System.arraycopy(data,0,databuff,datapos,data.length);
        datapos += data.length;

        databuff[datapos] = (byte) checkXor(datapos,false);
        datapos++;
    }

    public byte[]  EndData(){
        databuff[datapos] = 0x7e;
        datapos+=1;
        return TransData();
    }

    public void PackageHead(int id,int seq){

    }



}
